package simple_sql

import (
	"database/sql"
	"fmt"
	"strings"
)

// QueryUpdate 结构体用于构建和执行SQL更新语句。
// 它包含数据库连接、表名、WHERE子句构建器、WHERE子句的参数以及可能的错误。
type QueryUpdate struct {
	query     *sql.DB
	tx        *sql.Tx
	tableName string
	where     strings.Builder
	whereArgs []any
	err       error
}

// Where 方法用于添加SQL语句中的WHERE子句。
// 它接受一个Operator类型的切片，将其转换为SQL条件，并添加到查询中。
func (q *QueryUpdate) Where(opList ...Operator) *QueryUpdate {
	// 如果查询条件有错误或过滤条件为空，则直接返回。
	if q.err != nil || opList == nil || len(opList) == 0 {
		return q
	}

	// 创建一个字符串构建器，用于构造过滤条件。
	var filter strings.Builder
	// 构造过滤条件并添加到where部分。
	for _, op := range opList {
		operator, value, err := op.toSql()
		if err != nil {
			q.err = err
			return q
		}
		if filter.Len() != 0 {
			filter.WriteString(" AND")
		}
		filter.WriteString(operator)
		q.whereArgs = append(q.whereArgs, value...)
	}
	// 判断是否首次的过滤条件，不是添加（AND、OR）
	q.where.WriteString(fmt.Sprintf("(%s )", filter.String()))

	// 返回Query指针，支持链式调用。
	return q
}

// And 方法用于添加AND逻辑到WHERE子句中。
// 它先添加一个"AND"关键字，然后调用Where方法添加具体的条件。
func (q *QueryUpdate) And(opList ...Operator) *QueryUpdate {
	if q.err != nil || opList == nil || len(opList) == 0 {
		return q
	}

	q.where.WriteString(" AND")
	q.Where(opList...)

	return q
}

// Or 方法用于添加OR逻辑到WHERE子句中。
// 它先添加一个"OR"关键字，然后调用Where方法添加具体的条件。
func (q *QueryUpdate) Or(opList ...Operator) *QueryUpdate {
	if q.err != nil || opList == nil || len(opList) == 0 {
		return q
	}

	q.where.WriteString(" OR")
	q.Where(opList...)

	return q
}

// Set 方法用于设置要更新的字段和值。
// 它接受一个键值对映射，生成相应的SET子句，并执行SQL更新语句。
func (q *QueryUpdate) Set(value map[string]any) (int64, error) {
	if q.err != nil {
		return 0, q.err
	}
	if value == nil || len(value) == 0 {
		return 0, fmt.Errorf("请设置要更新的字段")
	}

	// 构建SQL语句的SET部分。
	var sqlString strings.Builder
	sqlString.WriteString("UPDATE " + q.tableName + " SET ")

	var args []any
	var v []string
	for key, val := range value {
		args = append(args, val)
		v = append(v, key+"=?")
	}
	args = append(args, q.whereArgs...)

	// 组合SET部分和WHERE部分，生成完整的SQL语句。
	sqlString.WriteString(strings.Join(v, ", "))
	sqlString.WriteString(" WHERE " + q.where.String())

	var err error
	var result sql.Result
	// 执行SQL语句并返回受影响的行数。
	if q.tx != nil {
		result, err = q.tx.Exec(sqlString.String(), args...)
	} else {
		result, err = q.query.Exec(sqlString.String(), args...)
	}
	if err != nil {
		return 0, err
	}
	return result.RowsAffected()
}
